home *** CD-ROM | disk | FTP | other *** search
/ Power Hacker 2003 / Power_Hacker_2003.iso / Exploit and vulnerability / w00w00 / sectools / fragrouter / Libnet-0.99b / src / asn1.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-07-26  |  11.4 KB  |  433 lines

  1. /*
  2.  *  $Id: asn1.c,v 1.1.1.1 1999/05/18 15:33:42 dugsong Exp $
  3.  *
  4.  *  libnet
  5.  *  asn1.c -  Abstract Syntax Notation One routines
  6.  *
  7.  *  Abstract Syntax Notation One, ASN.1
  8.  *  As defined in ISO/IS 8824 and ISO/IS 8825
  9.  *  This implements a subset of the above International Standards that
  10.  *  is sufficient to implement SNMP.
  11.  *
  12.  *  Encodes abstract data types into a machine independent stream of bytes.
  13.  *
  14.  *  Copyright 1988, 1989, 1991, 1992 by Carnegie Mellon University
  15.  *  All rights reserved.
  16.  *
  17.  *  Permission to use, copy, modify, and distribute this software and its
  18.  *  documentation for any purpose and without fee is hereby granted,
  19.  *  provided that the above copyright notice appear in all copies and that
  20.  *  both that copyright notice and this permission notice appear in
  21.  *  supporting documentation, and that the name of CMU not be
  22.  *  used in advertising or publicity pertaining to distribution of the
  23.  *  software without specific, written prior permission.
  24.  *
  25.  *  CMU DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
  26.  *  ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
  27.  *  CMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
  28.  *  ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
  29.  *  WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
  30.  *  ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
  31.  *  SOFTWARE.
  32.  *
  33.  *  Copyright (c) 1998, 1999 Mike D. Schiffman <mike@infonexus.com>
  34.  *                           route|daemon9 <route@infonexus.com>
  35.  *  All rights reserved.
  36.  *
  37.  * Copyright (c) 1993, 1994, 1995, 1996, 1998
  38.  *    The Regents of the University of California.  All rights reserved.
  39.  *
  40.  * Redistribution and use in source and binary forms, with or without
  41.  * modification, are permitted provided that: (1) source code distributions
  42.  * retain the above copyright notice and this paragraph in its entirety, (2)
  43.  * distributions including binary code include the above copyright notice and
  44.  * this paragraph in its entirety in the documentation or other materials
  45.  * provided with the distribution, and (3) all advertising materials mentioning
  46.  * features or use of this software display the following acknowledgement:
  47.  * ``This product includes software developed by the University of California,
  48.  * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
  49.  * the University nor the names of its contributors may be used to endorse
  50.  * or promote products derived from this software without specific prior
  51.  * written permission.
  52.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
  53.  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
  54.  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  55.  */
  56.  
  57. #if (HAVE_CONFIG_H)
  58. #include "../include/config.h"
  59. #endif
  60. #include "../include/libnet.h"
  61.  
  62. u_char *
  63. build_asn1_int(u_char *data, int *datalen, u_char type, long *int_p, int int_s)
  64. {
  65.     /*
  66.      *  ASN.1 integer ::= 0x02 asnlength byte {byte}*
  67.      */
  68.      register long integer;
  69.      register u_long mask;
  70.  
  71.     if (int_s != sizeof (long))
  72.     {
  73.         return (NULL);
  74.     }
  75.     integer = *int_p;
  76.  
  77.     /*
  78.      *  Truncate "unnecessary" bytes off of the most significant end of this
  79.      *  2's complement integer.  There should be no sequence of 9 consecutive
  80.      *  1's or 0's at the most significant end of the integer.
  81.      */
  82.     mask = ((u_long) 0x1FF) << ((8 * (sizeof (long) - 1)) - 1);
  83.     /* mask is 0xFF800000 on a big-endian machine */
  84.  
  85.     while ((((integer & mask) == 0) || ((integer & mask) == mask)) && int_s > 1)
  86.     {
  87.         int_s--;
  88.         integer <<= 8;
  89.     }
  90.  
  91.     data = build_asn1_header(data, datalen, type, int_s);
  92.  
  93.     if (data == NULL || *datalen < int_s)
  94.     {
  95.         return (NULL);
  96.     }
  97.  
  98.     *datalen -= int_s;
  99.  
  100.     mask = ((u_long) 0xFF) << (8 * (sizeof(long) - 1));
  101.     /* mask is 0xFF000000 on a big-endian machine */
  102.  
  103.     while (int_s--)
  104.     {
  105.         *data++ = (u_char)((integer & mask) >> (8 * (sizeof (long) - 1)));
  106.         integer <<= 8;
  107.     }
  108.     return (data);
  109. }
  110.  
  111.  
  112. u_char *
  113. build_asn1_uint(u_char *data, int *datalen, u_char type, u_long *int_p,
  114.             int int_s)
  115. {
  116.     /*
  117.      *  ASN.1 integer ::= 0x02 asnlength byte {byte}*
  118.      */
  119.     register u_long integer;
  120.     register u_long mask;
  121.     int add_null_byte = 0;
  122.  
  123.     if (int_s != sizeof (long))
  124.     {
  125.         return (NULL);
  126.     }
  127.     integer = *int_p;
  128.  
  129.     mask = ((u_long) 0xFF) << (8 * (sizeof (long) - 1));
  130.     /* mask is 0xFF000000 on a big-endian machine */
  131.  
  132.     if ((u_char)((integer & mask) >> (8 * (sizeof (long) - 1))) & 0x80)
  133.     {
  134.         /* if MSB is set */
  135.         add_null_byte = 1;
  136.         int_s++;
  137.     }
  138.     else
  139.     {
  140.         /*
  141.          * Truncate "unnecessary" bytes off of the most significant end of this
  142.          * 2's complement integer.  There should be no sequence of 9
  143.          * consecutive 1's or 0's at the most significant end of the
  144.          * integer.
  145.          */
  146.         mask = ((u_long) 0x1FF) << ((8 * (sizeof(long) - 1)) - 1);
  147.         /* mask is 0xFF800000 on a big-endian machine */
  148.  
  149.         while (((integer & mask) == 0) && int_s > 1)
  150.         {
  151.             int_s--;
  152.             integer <<= 8;
  153.         }
  154.     }
  155.  
  156.     data = build_asn1_header(data, datalen, type, int_s);
  157.  
  158.     if (data == NULL || *datalen < int_s)
  159.     {
  160.         return (NULL);
  161.     }
  162.  
  163.     *datalen -= int_s;
  164.  
  165.     if (add_null_byte == 1)
  166.     {
  167.         *data++ = '\0';
  168.         int_s--;
  169.     }
  170.  
  171.     mask = ((u_long) 0xFF) << (8 * (sizeof(long) - 1));
  172.     /* mask is 0xFF000000 on a big-endian machine */
  173.  
  174.     while (int_s--)
  175.     {
  176.         *data++ = (u_char)((integer & mask) >> (8 * (sizeof (long) - 1)));
  177.         integer <<= 8;
  178.     }
  179.     return (data);
  180. }
  181.  
  182.  
  183. u_char *
  184. build_asn1_string(u_char *data, int *datalen, u_char type, u_char *string,
  185.             int str_s)
  186. {
  187.  
  188.     /*
  189.      *  ASN.1 octet string ::= primstring | cmpdstring
  190.      *  primstring ::= 0x04 asnlength byte {byte}*
  191.      *  cmpdstring ::= 0x24 asnlength string {string}*
  192.      *  This code will never send a compound string.
  193.      */
  194.     data = build_asn1_header(data, datalen, type, str_s);
  195.  
  196.     if (data == NULL || *datalen < str_s)
  197.     {
  198.         return (NULL);
  199.     }
  200.     memmove(data, string, str_s);
  201.     *datalen -= str_s;
  202.  
  203.     return (data + str_s);
  204. }
  205.  
  206.  
  207. u_char *
  208. build_asn1_header(u_char *data, int *datalen, u_char type, int len)
  209. {
  210.     if (*datalen < 1)
  211.     {
  212.         return (NULL);
  213.     }
  214.     *data++ = type;
  215.     (*datalen)--;
  216.  
  217.     return (build_asn1_length(data, datalen, len));
  218. }
  219.  
  220.  
  221. u_char *
  222. build_asn1_sequence(u_char *data, int *datalen, u_char type, int len)
  223. {
  224.     *datalen -= 4;
  225.     if (*datalen < 0)
  226.     {
  227.         *datalen += 4;       /* fix up before punting */
  228.         return (NULL);
  229.     }
  230.     *data++ = type;
  231.     *data++ = (u_char)(0x02 | ASN_LONG_LEN);
  232.     *data++ = (u_char)((len >> 8) & 0xFF);
  233.     *data++ = (u_char)(len & 0xFF);
  234.     return (data);
  235. }
  236.  
  237.  
  238. u_char *
  239. build_asn1_length(u_char *data, int *datalen, int len)
  240. {
  241.     u_char *start_data = data;
  242.  
  243.     /* no indefinite lengths sent */
  244.     if (len < 0x80)
  245.     {
  246.         if (*datalen < 1)
  247.         {
  248.             return (NULL);
  249.         }
  250.         *data++ = (u_char)len;
  251.     }
  252.     else if (len <= 0xFF)
  253.     {
  254.         if (*datalen < 2)
  255.         {
  256.             return (NULL);
  257.         }
  258.         *data++ = (u_char)(0x01 | ASN_LONG_LEN);
  259.         *data++ = (u_char)len;
  260.     }
  261.     else    /* 0xFF < len <= 0xFFFF */
  262.     {
  263.         if (*datalen < 3)
  264.         {
  265.             return (NULL);
  266.         }
  267.         *data++ = (u_char)(0x02 | ASN_LONG_LEN);
  268.         *data++ = (u_char)((len >> 8) & 0xFF);
  269.         *data++ = (u_char)(len & 0xFF);
  270.     }
  271.     *datalen -= (data - start_data);
  272.     return (data);
  273. }
  274.  
  275.  
  276. u_char *
  277. build_asn1_objid(u_char *data, int *datalen, u_char type, oid *objid,
  278.             int objidlen)
  279. {
  280.     /*
  281.      *  ASN.1 objid ::= 0x06 asnlength subidentifier {subidentifier}*
  282.      *  subidentifier ::= {leadingbyte}* lastbyte
  283.      *  leadingbyte ::= 1 7bitvalue
  284.      *  lastbyte ::= 0 7bitvalue
  285.      */
  286.     int asnlen;
  287.     register oid *op = objid;
  288.     u_char objid_size[MAX_OID_LEN];
  289.     register u_long objid_val;
  290.     u_long first_objid_val;
  291.     register int i;
  292.  
  293.     /* check if there are at least 2 sub-identifiers */
  294.     if (objidlen < 2)
  295.     {
  296.         /* there are not, so make OID have two with value of zero */
  297.         objid_val = 0;
  298.         objidlen  = 2;
  299.     }
  300.     else
  301.     {
  302.         /* combine the first two values */
  303.         objid_val = (op[0] * 40) + op[1];
  304.         op += 2;
  305.     }
  306.     first_objid_val = objid_val;
  307.  
  308.     /* calculate the number of bytes needed to store the encoded value */
  309.     for (i = 1, asnlen = 0;;)
  310.     {
  311.         if (objid_val < (unsigned)0x80)
  312.         {
  313.             objid_size[i] = 1;
  314.             asnlen += 1;
  315.         }
  316.         else if (objid_val < (unsigned)0x4000)
  317.         {
  318.             objid_size[i] = 2;
  319.             asnlen += 2;
  320.         }
  321.         else if (objid_val < (unsigned)0x200000)
  322.         {
  323.             objid_size[i] = 3;
  324.             asnlen += 3;
  325.         }
  326.         else if (objid_val < (unsigned)0x10000000)
  327.         {
  328.             objid_size[i] = 4;
  329.             asnlen += 4;
  330.         }
  331.         else
  332.         {
  333.             objid_size[i] = 5;
  334.             asnlen += 5;
  335.         }
  336.         i++;
  337.         if (i >= objidlen)
  338.         {
  339.             break;
  340.         }
  341.         objid_val = *op++;
  342.     }
  343.  
  344.     /* store the ASN.1 tag and length */
  345.     data = build_asn1_header(data, datalen, type, asnlen);
  346.     if (data == NULL || *datalen < asnlen)
  347.     {
  348.         return (NULL);
  349.     }
  350.  
  351.     /* store the encoded OID value */
  352.     for (i = 1, objid_val = first_objid_val, op = objid + 2; i < objidlen; i++)
  353.     {
  354.         if (i != 1)
  355.         {
  356.             objid_val = *op++;
  357.         }
  358.         switch (objid_size[i])
  359.         {
  360.             case 1:
  361.                 *data++ = (u_char)objid_val;
  362.                 break;
  363.  
  364.             case 2:
  365.                 *data++ = (u_char)((objid_val >> 7) | 0x80);
  366.                 *data++ = (u_char)(objid_val & 0x07f);
  367.                 break;
  368.             case 3:
  369.                 *data++ = (u_char)((objid_val >> 14) | 0x80);
  370.                 *data++ = (u_char)((objid_val >> 7 & 0x7f) | 0x80);
  371.                 *data++ = (u_char)(objid_val & 0x07f);
  372.                 break;
  373.  
  374.             case 4:
  375.                 *data++ = (u_char)((objid_val >> 21) | 0x80);
  376.                 *data++ = (u_char)((objid_val >> 14 & 0x7f) | 0x80);
  377.                 *data++ = (u_char)((objid_val >> 7 & 0x7f) | 0x80);
  378.                 *data++ = (u_char)(objid_val & 0x07f);
  379.                 break;
  380.  
  381.             case 5:
  382.                 *data++ = (u_char)((objid_val >> 28) | 0x80);
  383.                 *data++ = (u_char)((objid_val >> 21 & 0x7f) | 0x80);
  384.                 *data++ = (u_char)((objid_val >> 14 & 0x7f) | 0x80);
  385.                 *data++ = (u_char)((objid_val >> 7 & 0x7f) | 0x80);
  386.                 *data++ = (u_char)(objid_val & 0x07f);
  387.                 break;
  388.         }
  389.     }
  390.  
  391.     /* return the length and data ptr */
  392.     *datalen -= asnlen;
  393.     return (data);
  394. }
  395.  
  396.  
  397. u_char *
  398. build_asn1_null(u_char *data, int *datalen, u_char type)
  399. {
  400.     /*
  401.      *  ASN.1 null ::= 0x05 0x00
  402.      */       
  403.     return (build_asn1_header(data, datalen, type, 0));
  404. }
  405.  
  406.  
  407. u_char *
  408. build_asn1_bitstring(u_char *data, int *datalen, u_char type, u_char *string,
  409.             int str_s)
  410. {
  411.  
  412.     /*
  413.      *  ASN.1 bit string ::= 0x03 asnlength unused {byte}*
  414.      */
  415.     if (str_s < 1 || *string > 7)
  416.     {
  417.         return (NULL);
  418.     }
  419.     data = build_asn1_header(data, datalen, type, str_s);
  420.  
  421.     if (data == NULL || *datalen < str_s)
  422.     {
  423.         return (NULL);
  424.     }
  425.  
  426.     memmove(data, string, str_s);
  427.     *datalen -= str_s;
  428.  
  429.     return (data + str_s);
  430. }
  431.  
  432. /* EOF */
  433.